package com.xh3140.xwidget.dialog;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.ColorInt;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.annotation.Size;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.MutableLiveData;

import com.xh3140.xwidget.dialog.callback.ConfigParamsCallback;
import com.xh3140.xwidget.dialog.callback.ConfigParamsListCallback;
import com.xh3140.xwidget.dialog.callback.ConfigViewCallback;
import com.xh3140.xwidget.dialog.listener.OnClickButtonListener;
import com.xh3140.xwidget.dialog.params.ItemParams;
import com.xh3140.xwidget.dialog.params.ListParams;
import com.xh3140.xwidget.dialog.view.FooterView;
import com.xh3140.xwidget.dialog.view.HeaderView;
import com.xh3140.xwidget.dialog.view.ItemView;
import com.xh3140.xwidget.dialog.view.ListView;
import com.xh3140.xwidget.dialog.view.RootView;

import java.util.Arrays;
import java.util.List;

/**
 * 列表对话框
 */
@SuppressWarnings("unused")
public final class ListDialog extends BaseDialog<ListView> {
  private ListParams mListParams;
  private OnClickButtonListener<ListDialog> mOnClickButtonListener;

  /**
   * 获取单选的选取位置索引
   * 注意：没有选中任何项目时返回负数(-1)
   */
  public int getCheckedIndex() {
    return requireRootView().requireBodyView().getCheckedIndex();
  }

  /**
   * 获取多选的选取位置索引列表
   * 注意：没有选中任何项目时返回空列表
   */
  public List<Integer> getCheckedIndexList() {
    return requireRootView().requireBodyView().getCheckedIndexList();
  }

  @NonNull
  @Override
  protected RootView<ListView> createRootView(@NonNull Context context) {
    final ListDialog dialog = this;
    return new RootView<ListView>(context) {
      @Override
      protected HeaderView createHeaderView(@NonNull Context context) {
        return new HeaderView(context).configView(mHeaderParams);
      }

      @Override
      protected ListView createBodyView(@NonNull Context context) {
        return new ListView(context).configView(mListParams);
      }

      @Override
      protected FooterView createFooterView(@NonNull Context context) {
        return new FooterView(context).configView(dialog, mFooterParams, mOnClickButtonListener);
      }
    };
  }

  @Override
  public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    ViewModel.getDefault(this, ViewModel.class).configListDialogParams(this);
    return super.onCreateView(inflater, container, savedInstanceState);
  }

  /**
   * 数据状态保存
   * 由于屏幕方向旋转等情况会导致构建数据丢失，所以需要保存
   */
  public static final class ViewModel extends BaseDialog.ViewModel {
    private final MutableLiveData<ListParams> mListParamsData = new MutableLiveData<>();
    private final MutableLiveData<OnClickButtonListener<ListDialog>> mOnClickButtonListenerData = new MutableLiveData<>();

    private void configListDialogParams(@NonNull final ListDialog dialog) {
      configBaseDialogParams(dialog);
      if (dialog.mListParams == null) {
        dialog.mListParams = mListParamsData.getValue();
      } else {
        mListParamsData.postValue(dialog.mListParams);
      }
      if (dialog.mOnClickButtonListener == null) {
        dialog.mOnClickButtonListener = mOnClickButtonListenerData.getValue();
      } else {
        mOnClickButtonListenerData.postValue(dialog.mOnClickButtonListener);
      }
    }
  }

  /**
   * 列表对话框构建器
   * 设置输入对话框属性
   */
  public static final class Builder extends BaseDialog.Builder<ListDialog, Builder> {
    /**
     * 对话框列表主体视图配置属性
     */
    private final ListParams mListParams;
    /**
     * 是否修改过首部部件(标题和副标题)的外边距
     */
    private boolean mEditHeadPadding = false;

    public Builder(@NonNull Context context, @IntRange(from = 0) int itemCount) {
      super(context);
      mListParams = new ListParams(context, itemCount);
      mDialogParams.showDividers = RootView.SHOW_DIVIDER_MIDDLE;
    }

    public Builder(@NonNull FragmentActivity activity, @IntRange(from = 0) int itemCount) {
      super(activity);
      mListParams = new ListParams(mDialogParams.context, itemCount);
      mDialogParams.showDividers = RootView.SHOW_DIVIDER_MIDDLE;
    }

    public Builder(@NonNull Fragment fragment, @IntRange(from = 0) int itemCount) {
      super(fragment);
      mListParams = new ListParams(mDialogParams.context, itemCount);
      mDialogParams.showDividers = RootView.SHOW_DIVIDER_MIDDLE;
    }

    @Override
    public Builder setTitlePadding(@Nullable int[] padding) {
      mEditHeadPadding = true;
      return super.setTitlePadding(padding);
    }

    @Override
    public Builder setSubtitlePadding(@Nullable int[] padding) {
      mEditHeadPadding = true;
      return super.setSubtitlePadding(padding);
    }

    /**
     * 配置列表对话框专有属性
     * 列表对话框相对于一般的对话框，在首部视图与主题视图间默认多了一条分割线
     * 在默认情况下需要配置首部视图的部件间距
     */
    private void configListDialogOwnParams() {
      if (mEditHeadPadding || mDialogParams.showDividers < 0) {
        return;
      }
      if (mHeaderParams.title.text != null) {
        if (mHeaderParams.subtitle.text == null) {
          if (mHeaderParams.title.padding != null) {
            mHeaderParams.title.padding[3] = mHeaderParams.dp2px(8);
          }
        } else {
          if (mHeaderParams.subtitle.padding != null) {
            mHeaderParams.subtitle.padding[3] = mHeaderParams.dp2px(8);
          }
        }
      } else {
        if (mHeaderParams.subtitle.text != null) {
          if (mHeaderParams.subtitle.padding != null) {
            mHeaderParams.subtitle.padding[1] = mHeaderParams.dp2px(16);
            mHeaderParams.subtitle.padding[3] = mHeaderParams.dp2px(8);
          }
        }
      }
    }

    /**
     * 构建对话框
     * 这个方法应该在所有配置结束后调用
     */
    @Override
    public ListDialog build() {
      configListDialogOwnParams();
      final ListDialog dialog = new ListDialog();
      dialog.mDialogParams = mDialogParams;
      dialog.mHeaderParams = mHeaderParams;
      dialog.mFooterParams = mFooterParams;
      dialog.mListParams = mListParams;
      dialog.mOnClickButtonListener = mOnClickButtonListener;
      return dialog;
    }

    /**
     * 配置列表主体视图属性
     *
     * @param callback 配置回调
     */
    public Builder configListParams(@NonNull ConfigParamsCallback<ListParams> callback) {
      callback.callback(mListParams);
      return this;
    }

    /**
     * 配置列表主体视图项目属性
     *
     * @param position 项目位置索引
     * @param callback 配置回调
     */
    public Builder configListItemParams(int position, @NonNull ConfigParamsCallback<ItemParams> callback) {
      callback.callback(mListParams.items.get(position));
      return this;
    }

    /**
     * 配置列表主体视图所有项目属性
     *
     * @param callback 配置回调
     */
    public Builder configListItemsParams(@NonNull ConfigParamsListCallback<ItemParams> callback) {
      callback.callback(mListParams.items);
      return this;
    }

    /**
     * 设置列表主体视图是否是单选列表
     *
     * @param radio 是否是单选列表
     */
    public Builder setListRadio(boolean radio) {
      mListParams.radio = radio;
      return this;
    }

    /**
     * 设置列表主体视图是否有分割线
     *
     * @param hasDivider 标志
     */
    public Builder setListHasDivider(boolean hasDivider) {
      mListParams.hasDivider = hasDivider;
      return this;
    }

    /**
     * 设置列表主体视图分割线颜色
     *
     * @param color 颜色 argb
     */
    public Builder setListDividerColor(@ColorInt int color) {
      mListParams.hasDivider = true;
      mListParams.dividerColor = color;
      return this;
    }

    /**
     * 设置列表主体视图分割线厚度 px
     *
     * @param thickness 厚度 px
     */
    public Builder setListDividerThickness(int thickness) {
      mListParams.hasDivider = true;
      mListParams.dividerThickness = thickness;
      return this;
    }

    /**
     * 设置列表主体视图单选默认的选取位置索引
     *
     * @param index 位置索引
     */
    public Builder setCheckedIndex(int index) {
      mListParams.radio = true;
      mListParams.checkedIndex = index;
      mListParams.items.get(index).checked = true;
      return this;
    }

    /**
     * 设置列表主体视图多选默认的选取位置索引组
     *
     * @param indexList 位置索引组
     */
    public Builder setCheckedIndexList(List<Integer> indexList) {
      mListParams.radio = false;
      mListParams.checkedIndexList = indexList;
      for (Integer index : indexList) {
        mListParams.items.get(index).checked = true;
      }
      return this;
    }

    /**
     * 设置列表主体视图多选默认的选取位置索引组
     *
     * @param indexArray 位置索引组
     */
    public Builder setCheckedIndexList(Integer... indexArray) {
      mListParams.radio = false;
      mListParams.checkedIndexList = Arrays.asList(indexArray);
      for (Integer index : indexArray) {
        mListParams.items.get(index).checked = true;
      }
      return this;
    }

    /**
     * 设置列表主体视图配置回调
     * 拥有绝对控制权的回调，它在其他属性配置结束后回调
     * 一般情况不要使用它，除非提供的现有配置属性不满足需求
     *
     * @param callback 配置回调
     */
    public Builder setListViewCallback(@Nullable ConfigViewCallback<ListView> callback) {
      mListParams.callback = callback;
      return this;
    }

    /**
     * 设置列表主体视图项目文本列表
     *
     * @param texts 项目文本列表
     */
    public Builder setListItemsText(List<CharSequence> texts) {
      for (int i = 0; i < texts.size(); ++i) {
        mListParams.items.get(i).text = texts.get(i);
      }
      return this;
    }

    /**
     * 设置列表主体视图项目文本列表
     *
     * @param texts 项目文本列表
     */
    public Builder setListItemsText(CharSequence... texts) {
      for (int i = 0; i < texts.length; ++i) {
        mListParams.items.get(i).text = texts[i];
      }
      return this;
    }

    /**
     * 设置列表主体视图项目文本列表
     *
     * @param index 单选默认的选取位置索引
     * @param texts 项目文本列表
     */
    public Builder setListItemsText(int index, List<CharSequence> texts) {
      mListParams.radio = true;
      mListParams.checkedIndex = index;
      mListParams.items.get(index).checked = true;
      for (int i = 0; i < texts.size(); ++i) {
        mListParams.items.get(i).text = texts.get(i);
      }
      return this;
    }

    /**
     * 设置列表主体视图项目文本列表
     *
     * @param index 单选默认的选取位置索引
     * @param texts 项目文本列表
     */
    public Builder setListItemsText(int index, CharSequence... texts) {
      mListParams.radio = true;
      mListParams.checkedIndex = index;
      mListParams.items.get(index).checked = true;
      for (int i = 0; i < texts.length; ++i) {
        mListParams.items.get(i).text = texts[i];
      }
      return this;
    }

    /**
     * 设置列表主体视图项目文本列表
     *
     * @param indexList 多选默认的选取位置索引组
     * @param texts     项目文本列表
     */
    public Builder setListItemsText(List<Integer> indexList, List<CharSequence> texts) {
      mListParams.radio = false;
      mListParams.checkedIndexList = indexList;
      for (Integer index : indexList) {
        mListParams.items.get(index).checked = true;
      }
      for (int i = 0; i < texts.size(); ++i) {
        mListParams.items.get(i).text = texts.get(i);
      }
      return this;
    }

    /**
     * 设置列表主体视图项目文本列表
     *
     * @param indexList 多选默认的选取位置索引组
     * @param texts     项目文本列表
     */
    public Builder setListItemsText(List<Integer> indexList, CharSequence... texts) {
      mListParams.radio = false;
      mListParams.checkedIndexList = indexList;
      for (Integer index : indexList) {
        mListParams.items.get(index).checked = true;
      }
      for (int i = 0; i < texts.length; ++i) {
        mListParams.items.get(i).text = texts[i];
      }
      return this;
    }

    /**
     * 设置列表主体视图项目是否被选中
     *
     * @param position 项目位置索引
     * @param checked  是否被选中
     */
    public Builder setListItemChecked(int position, boolean checked) {
      mListParams.items.get(position).checked = checked;
      return this;
    }

    /**
     * 设置列表主体视图项目文本字体大小 sp
     *
     * @param position 项目位置索引
     * @param textSize 字体大小
     */
    public Builder setListItemTextSize(int position, float textSize) {
      mListParams.items.get(position).textSize = textSize;
      return this;
    }

    /**
     * 设置列表主体视图项目文本字体颜色 argb
     *
     * @param position  项目位置索引
     * @param textColor 字体颜色
     */
    public Builder setListItemTextColor(int position, @ColorInt int textColor) {
      mListParams.items.get(position).textColor = textColor;
      return this;
    }

    /**
     * 设置列表主体视图项目文本字体样式
     *
     * @param position 项目位置索引
     * @param typeface 字体样式
     */
    public Builder setListItemTypeface(int position, int typeface) {
      mListParams.items.get(position).typeface = typeface;
      return this;
    }

    /**
     * 设置列表主体视图项目文本位置
     *
     * @param position 项目位置索引
     * @param gravity  位置
     */
    public Builder setListItemGravity(int position, int gravity) {
      mListParams.items.get(position).gravity = gravity;
      return this;
    }

    /**
     * 设置列表主体视图项目背景颜色 argb
     *
     * @param position        项目位置索引
     * @param backgroundColor 背景颜色
     */
    public Builder setListItemBackgroundColor(int position, @ColorInt int backgroundColor) {
      mListParams.items.get(position).backgroundColor = backgroundColor;
      return this;
    }

    /**
     * 设置列表主体视图项目按下状态时的背景颜色 argb
     *
     * @param position        项目位置索引
     * @param backgroundColor 背景颜色
     */
    public Builder setListItemPressedBackgroundColor(int position, @ColorInt int backgroundColor) {
      mListParams.items.get(position).pressedBackgroundColor = backgroundColor;
      return this;
    }

    /**
     * 设置列表主体视图项目内边距
     * <p>
     * 格式：[start, top, end, bottom] px
     *
     * @param position 项目位置索引
     * @param padding  边距
     */
    public Builder setListItemPadding(int position, @Nullable @Size(4) int[] padding) {
      mListParams.items.get(position).padding = padding;
      return this;
    }

    /**
     * 设置列表主体视图项目内边距
     *
     * @param position 项目位置索引
     * @param padding  边距 px
     */
    public Builder setListItemPadding(int position, @Px int padding) {
      return setListItemPadding(position, new int[]{padding, padding, padding, padding});
    }

    /**
     * 设置列表主体视图项目内边距
     *
     * @param position 项目位置索引
     * @param left     左边距 px
     * @param top      上边距 px
     * @param right    右边距 px
     * @param bottom   下边距 px
     */
    public Builder setListItemPadding(int position, @Px int left, @Px int top, @Px int right, @Px int bottom) {
      return setListItemPadding(position, new int[]{left, top, right, bottom});
    }

    /**
     * 设置列表主体视图项目配置回调
     * 拥有绝对控制权的回调，它在其他属性配置结束后回调
     * 一般情况不要使用它，除非提供的现有配置属性不满足需求
     *
     * @param position 项目位置索引
     * @param callback 配置回调
     */
    public Builder setListItemViewCallback(int position, @Nullable ConfigViewCallback<ItemView> callback) {
      mListParams.items.get(position).callback = callback;
      return this;
    }
  }
}
